/************************************************************************
                                                                     
   Xceed Ultimate ListBox for Silverlight                                                                                                                                            
   Copyright (C) 2010 Xceed Software Inc.    
                                                                     
   This program is provided to you under the terms of the GNU General Public  
   License version 2 as published by the Free Software Foundation. 
        
   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY, without even the implied warranty of 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License along 
   with this program, if not, write to the Free Software Foundation, Inc., 
   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

   This program can be provided to you by Xceed Software Inc. under a
   proprietary commercial license agreement for use in non-Open Source
   projects. Visit Xceed.com to find the commercial edition of 
   Xceed Ultimate ListBox for Silverlight.                                    
                                                                      
 **********************************************************************/

using System.Collections.Generic;
using System.Windows.Media.Animation;

namespace Xceed.Silverlight.ListBox
{
  internal class LoadingTransitionAnimation : TransitionAnimation
  {
    internal LoadingTransitionAnimation( ListBoxAnimationSettings animationSettings )
      : base( animationSettings.GetLoadingDuration() )
    {
      m_fadeInEasing = new PowerEase()
      {
        Power = 2,
        EasingMode = EasingMode.EaseIn
      };

      m_fadeOutEasing = new PowerEase()
      {
        Power = 2,
        EasingMode = EasingMode.EaseOut
      };
    }

    internal override void AddContainer( ListBoxContainer container )
    {
      if( !this.IsRunning )
        return;

      LayoutChangeInfo layoutChange = this.CreateLayoutChangeInfo();

      if( this.PrepareContainer( container, layoutChange ) )
      {
        //Update the element with start time, ensure that as soon as "start" completes, state if correct for all items.
        if( !this.UpdateContainer( 0d, container ) )
        {
          //If both preparation let pass the item and update did not filter it out, mark the item as managed by TransitionAnimation
          this.HandledItems.Add( container );
        }
      }
    }

    internal override void DetermineLayoutChangesCore( Dictionary<ListBoxContainer, LayoutChangeInfo> changedElements )
    {
      //Nothing additional to do
    }

    internal override bool PrepareContainerCore( ListBoxContainer container, LayoutChangeInfo changeInfo )
    {
      if( changeInfo == null )
        throw new ListBoxInternalException();

      if( changeInfo.ChangeType == ChangeType.ElementAdded )
      {
        OpacityAnimation opacityAnimation = new OpacityAnimation();
        opacityAnimation.OpacityChange = -changeInfo.OpacityChange;
        ( ( IAnimation )opacityAnimation ).AnimationDirection = AnimationDirection.ToReferencePosition;
        ( ( IAnimation )opacityAnimation ).EasingFunction = m_fadeInEasing;
        ( ( IAnimation )opacityAnimation ).ParentTransition = this;
        container.AddAnimation( opacityAnimation );

        RotateAnimation rotateAnimation = new RotateAnimation();
        rotateAnimation.AngleChange = changeInfo.AngleChange;
        ( ( IAnimation )rotateAnimation ).EasingFunction = m_fadeInEasing;
        ( ( IAnimation )rotateAnimation ).ParentTransition = this;
        container.AddAnimation( rotateAnimation );
        return true;
      }
      else if( changeInfo.ChangeType == ChangeType.ElementRemoved )
      {
        OpacityAnimation opacityAnimation = new OpacityAnimation();
        opacityAnimation.OpacityChange = -changeInfo.OpacityChange;
        ( ( IAnimation )opacityAnimation ).AnimationDirection = AnimationDirection.FromReferencePosition;
        ( ( IAnimation )opacityAnimation ).EasingFunction = m_fadeOutEasing;
        ( ( IAnimation )opacityAnimation ).ParentTransition = this;
        container.AddAnimation( opacityAnimation );

        RotateAnimation rotateAnimation = new RotateAnimation();
        rotateAnimation.AngleChange = changeInfo.AngleChange;
        ( ( IAnimation )rotateAnimation ).EasingFunction = m_fadeInEasing;
        ( ( IAnimation )rotateAnimation ).ParentTransition = this;
        container.AddAnimation( rotateAnimation );
        return true;
      }
      else
      {
        return false; //for "changed" elements, do not perform any transition (anyway, there should not be any).
      }
    }

    internal override bool UpdateContainerCore( double normalizedElapsedTime, ListBoxContainer container )
    {

      if( container == null )
        throw new ListBoxInternalException();

      container.UpdateAnimations( normalizedElapsedTime );

      //There is no custom animations in this transition, only those handled by the EasingFunctions.
      //Since I have no custom timeline, I do not have to decide when its "finished". Returning false
      //will just make it so that the animation will proceed for every frame of every item.
      return false;
    }

    internal override void CleanContainerCore( ListBoxContainer container )
    {
      if( container == null )
        throw new ListBoxInternalException();
    }

    internal override LayoutChangeInfo CreateLayoutChangeInfo()
    {
      return new LayoutChangeInfo();
    }

    private IEasingFunction m_fadeOutEasing;
    private IEasingFunction m_fadeInEasing;
  }
}
